package org.nlp2rdf.navigator.client;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.nlp2rdf.navigator.client.common.ClassificationResultDTO;
import org.nlp2rdf.navigator.client.common.ExampleDTO;
import org.nlp2rdf.navigator.client.common.KnowledgeBaseDescriptorDTO;
import org.nlp2rdf.navigator.client.common.LearnedConceptDTO;
import org.nlp2rdf.navigator.client.common.RelatedConceptsDTO;
import org.nlp2rdf.navigator.client.common.SearchResultDTO;
import org.nlp2rdf.navigator.client.common.UserDTO;
import org.nlp2rdf.navigator.client.common.LearnedConceptDTO.MyExamples;
import org.nlp2rdf.navigator.client.exception.NKEException;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Application implements EntryPoint {

	/**
	 * This property hides a bug in the backend refine and specialize cannot be
	 * called unless DL-Learner learnt something
	 */
	@Deprecated
	public boolean learningWasExecutedOnce = false;

	final DockPanel dockPanel;

	KnowledgeBaseDescriptorDTO knowledgeBaseDescriptorDTO = null;

	WorkerServiceAsync worker = WorkerServiceAsync.Util.getInstance();

	LearnedConceptWidget learnedConcepts;

	SearchWidget searchWidget;

	SearchResultWidget searchResultsWidget;

	PositiveNegativeWidget positiveNegativeWidget;

	RelatedConceptsWidget relatedConceptWidget;

	StoredConceptWidget storedConceptWidget;

	LoginWidget loginWidget;

	HeadWidget headWidget;

	ClassifiedInstancesWidget classfiedInstancesWidget;

	private UserDTO user;

	public Application() {
		dockPanel = new DockPanel();
		RootPanel.get().add(dockPanel);
	}

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		headWidget = new HeadWidget(this, new LoginWidget(this));

		this.getWorkerService().listAvailableKnowledgeBases(
				new AsyncCallback<Set<KnowledgeBaseDescriptorDTO>>() {
					public void onSuccess(Set<KnowledgeBaseDescriptorDTO> knowledgeBaseDescriptorDTOs) {
						headWidget.setKnowledgeBaseDescriptorDTOs(knowledgeBaseDescriptorDTOs);
						dockPanel.add(headWidget, DockPanel.NORTH);
					}

					public void onFailure(Throwable arg0) {
						reportError(arg0);
					}
				});
	}

	public void changeKnowledgeBase(String kbId) {
		if (kbId == null) {
			knowledgeBaseDescriptorDTO = null;
			reset();
		} else {

			this.getWorkerService().changeKnowledgeBase(kbId,
					new AsyncCallback<KnowledgeBaseDescriptorDTO>() {
						public void onSuccess(KnowledgeBaseDescriptorDTO arg0) {
							knowledgeBaseDescriptorDTO = arg0;
							reset();
						}

						public void onFailure(Throwable arg0) {
							reportError(arg0);
						}
					});
		}
	}

	//		

	// Basic Layout

	public void reset() {

		List<Widget> toBeRemoved = new ArrayList<Widget>();
		for (int i = 0; i < dockPanel.getWidgetCount(); i++) {
			if (!(dockPanel.getWidget(i) instanceof HeadWidget)) {
				toBeRemoved.add(dockPanel.getWidget(i));
			}
		}
		for (Widget widget : toBeRemoved) {
			dockPanel.remove(widget);

		}

		if (knowledgeBaseDescriptorDTO == null) {
			return;
		}

		dockPanel.add(headLine(), DockPanel.NORTH);

		VerticalPanel searchPanels = new VerticalPanel();
		searchPanels.setWidth("400px");
		dockPanel.add(searchPanels, DockPanel.WEST);

		VerticalPanel learnPanels = new VerticalPanel();
		dockPanel.add(learnPanels, DockPanel.CENTER);
		learnPanels.setWidth("400px");

		VerticalPanel savedConceptPanels = new VerticalPanel();
		dockPanel.add(savedConceptPanels, DockPanel.EAST);
		savedConceptPanels.setWidth("400px");

		// the top search Panel creation
		searchWidget = new SearchWidget(this, knowledgeBaseDescriptorDTO.getAvailableSearches());
		searchPanels.add(searchWidget);

		// search results in the middle
		searchResultsWidget = new SearchResultWidget(this);
		searchPanels.add(searchResultsWidget);

		// learned Concepts on the bottom
		learnedConcepts = new LearnedConceptWidget(this);
		learnPanels.add(learnedConcepts);

		// selected examples on the right
		positiveNegativeWidget = new PositiveNegativeWidget(this);
		learnPanels.add(positiveNegativeWidget);

		// Matching concepts
		classfiedInstancesWidget = new ClassifiedInstancesWidget(this);
		searchPanels.add(classfiedInstancesWidget);

		// Concepts related to the selected
		relatedConceptWidget = new RelatedConceptsWidget(this);
		savedConceptPanels.add(relatedConceptWidget);

		// Concepts shared by Users
		storedConceptWidget = new StoredConceptWidget(this);
		savedConceptPanels.add(storedConceptWidget);

	}

	private Panel headLine() {
		String html = "<h1>" + knowledgeBaseDescriptorDTO.getApplicationLabel() + "</h1>\n" + "<div>"
				+ knowledgeBaseDescriptorDTO.getApplicationComment() + "</div>";
		HTMLPanel ret = new HTMLPanel(html);
		return ret;
	}

	public void reportError(Throwable error) {
		if (error instanceof NKEException) {
			Window.alert("NKEException:" + ((NKEException) error).getSymbol());
		} else {
			String errormsg = "";
			errormsg += error.getMessage();
			for (StackTraceElement e : error.getStackTrace()) {
				errormsg += e.toString() + "\n";
			}
			;
			Window.alert(errormsg);
		}

	}

	public void displaySearchResult(SearchResultDTO searchResult) {
		// TODO might be implemented more efficiently
		// searchResult.remove(positiveNegativeWidget.getPosList());
		// searchResult.remove(positiveNegativeWidget.getNegList());
		searchResultsWidget.updateSearchResults(searchResult);
		searchResultsWidget.collapse(false);
		classfiedInstancesWidget.collapse(true);
	}

	public void moveToPos(ExampleDTO exampleDTO) {
		positiveNegativeWidget.addPositive(exampleDTO);
	}

	public void moveToNeg(ExampleDTO exampleDTO) {
		positiveNegativeWidget.addNegative(exampleDTO);

	}
	
	public void loadPosNeg(MyExamples examples){
		positiveNegativeWidget.load(examples);
	}

	protected WorkerServiceAsync getWorkerService() {
		return worker;
	}

	public void displayLearnedConcept(LearnedConceptDTO dto) {
		// add the previous to the history
		if (learnedConcepts.getLearningResult() != null) {

		}
		learnedConcepts.update(dto);

		// load relatedConcepts
		getWorkerService().getRelatedConcepts(dto, new AsyncCallback<RelatedConceptsDTO>() {
			public void onSuccess(RelatedConceptsDTO rcDto) {
				relatedConceptWidget.update(rcDto);
			}

			public void onFailure(Throwable arg0) {
				reportError(arg0);
			}
		});

		// getWorkerService().incrementHitCount(dto, new AsyncCallback<Void>() {
		//			
		// public void onSuccess(Void arg0){
		// // nüscht
		// }
		//			
		// public void onFailure(Throwable arg0) {
		// reportError(arg0);
		//				
		// }
		// });

	}

	// public void displayConceptMatches(List<ExampleDTO> exampleDTOs) {
	// classfiedInstancesWidget.update(exampleDTOs);
	// searchResultsWidget.collapse(true);
	// classfiedInstancesWidget.collapse(false);
	//		
	// }
	public void displayClassificationResult(ClassificationResultDTO result) {
		// TODO might be implemented more efficiently
		// result.remove(positiveNegativeWidget.getPosList());
		// result.remove(positiveNegativeWidget.getNegList());
		classfiedInstancesWidget.update(result, this.learnedConcepts.getLearningResult());
		searchResultsWidget.collapse(true);
		classfiedInstancesWidget.collapse(false);

	}

	public void setUser(UserDTO user) {
		this.user = user;

	}

	public void notifyStoredConceptWidget() {
		this.storedConceptWidget.update();

	}

}
